home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libsock / serial.c < prev    next >
C/C++ Source or Header  |  1997-08-11  |  9KB  |  310 lines

  1. /* serial.c: Interface layer to serial HotSync connections
  2.  *
  3.  * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
  4.  * This is free software, licensed under the GNU Public License V2.
  5.  * See the file COPYING for details.
  6.  */
  7.  
  8. #include <errno.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include <fcntl.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-serial.h"
  17. #include "pi-inetserial.h"
  18. #include "pi-padp.h"
  19. #include "pi-cmp.h"
  20. #include "pi-dlp.h"
  21. #include "pi-syspkt.h"
  22.  
  23. #ifdef OS2
  24. #include <sys/select.h>
  25. #endif
  26.  
  27. static int pi_serial_listen(struct pi_socket *ps, int backlog);
  28. static int pi_serial_accept(struct pi_socket *ps, struct sockaddr *addr, int *addrlen);
  29. static int pi_serial_send(struct pi_socket *ps, void *msg, int len, unsigned int flags);
  30. static int pi_serial_recv(struct pi_socket *ps, void *msg, int len, unsigned int flags);
  31. static int pi_serial_tickle(struct pi_socket *ps);
  32. static int pi_serial_close(struct pi_socket * ps);
  33.  
  34. extern int dlp_trace;
  35.  
  36. int pi_serial_connect(struct pi_socket *ps, struct sockaddr *addr, int addrlen)
  37. {
  38.   struct cmp c;
  39.   struct pi_sockaddr * pa = (struct pi_sockaddr*)addr;
  40.  
  41.   if(ps->type == PI_SOCK_STREAM) {
  42.     ps->establishrate = 9600; /* Default PADP connection rate */
  43.     if (getenv("PILOTRATE"))
  44.             ps->establishrate = atoi(getenv("PILOTRATE"));
  45.     ps->rate = 9600; /* Mandatory CMP connection rate */
  46.   } else if(ps->type == PI_SOCK_RAW) {
  47.     ps->establishrate = ps->rate = 57600; /* Mandatory SysPkt connection rate */
  48.   }
  49.  
  50.   if ((addr->sa_family == PI_AF_INETSLP) || 
  51.       ((addr->sa_family == PI_AF_SLP) && (pa->pi_device[0] == ':'))) {
  52.     if (pi_inetserial_open(ps, addr, addrlen) == -1) {
  53.       return -1;     /* errno already set */
  54.     }
  55.   }
  56.   else {
  57.     if (pi_serial_open(ps, pa, addrlen) == -1) {
  58.       return -1;     /* errno already set */
  59.     }
  60.   }
  61.  
  62.   ps->raddr = malloc(addrlen);
  63.   memcpy(ps->raddr, addr, addrlen);
  64.   ps->raddrlen = addrlen;
  65.   ps->laddr = malloc(addrlen);
  66.   memcpy(ps->laddr, addr, addrlen);
  67.   ps->laddrlen = addrlen;
  68.    
  69.   if(ps->type == PI_SOCK_STREAM) {
  70.  
  71.     if(cmp_wakeup(ps, 38400)<0) /* Assume this box can't go over 38400 */
  72.       return -1;
  73.  
  74.     if(cmp_rx(ps, &c) < 0)
  75.       return -1; /* failed to read, errno already set */
  76.       
  77.     if(c.type == 2) {
  78.       /* CMP init packet */
  79.  
  80.       if(c.flags & 0x80) {
  81.         /* Change baud rate */
  82.         ps->rate = c.baudrate;
  83.         ps->serial_changebaud(ps);
  84.       }
  85.  
  86.     } else if(c.type == 3) {
  87.       /* CMP abort packet -- the other side didn't like us */
  88.       ps->serial_close(ps);
  89.  
  90. #ifdef DEBUG
  91.       fprintf(stderr,"Received CMP abort from client\n");
  92. #endif
  93.       errno = -EIO;
  94.       return -1;
  95.     }
  96.   }
  97.   ps->connected = 1;
  98.  
  99.   ps->initiator = 1; /* We initiated the link */
  100.   
  101.   ps->socket_listen = pi_serial_listen;
  102.   ps->socket_accept = pi_serial_accept;
  103.   ps->socket_close = pi_serial_close;
  104.   ps->socket_send = pi_serial_send;
  105.   ps->socket_recv = pi_serial_recv;
  106.   ps->socket_tickle = pi_serial_tickle;
  107.   
  108.   return 0;
  109. }
  110.  
  111. /* Bind address to a local socket */
  112.  
  113. int pi_serial_bind(struct pi_socket *ps, struct sockaddr *addr, int addrlen)
  114. {
  115.   struct pi_sockaddr * pa = (struct pi_sockaddr*)addr;
  116.   if(ps->type == PI_SOCK_STREAM) {
  117.     ps->establishrate = 9600; /* Default PADP connection rate */
  118.     if (getenv("PILOTRATE"))
  119.             ps->establishrate = atoi(getenv("PILOTRATE"));
  120.     ps->rate = 9600; /* Mandatory CMP conncetion rate */
  121.   } else if(ps->type == PI_SOCK_RAW) {
  122.     ps->establishrate = ps->rate = 57600; /* Mandatory SysPkt connection rate */
  123.   }
  124.  
  125.   if ((addr->sa_family == PI_AF_INETSLP) || 
  126.       ((addr->sa_family == PI_AF_SLP) && (pa->pi_device[0] == ':'))) {
  127.     if (pi_inetserial_open(ps, addr, addrlen) == -1) {
  128.       return -1;     /* errno already set */
  129.     }
  130.   }
  131.   else {
  132.     if (pi_serial_open(ps, pa, addrlen) == -1) {
  133.       return -1;     /* errno already set */
  134.     }
  135.   }
  136.   
  137.   ps->raddr = malloc(addrlen);
  138.   memcpy(ps->raddr, addr, addrlen);
  139.   ps->raddrlen = addrlen;
  140.   ps->laddr = malloc(addrlen);
  141.   memcpy(ps->laddr, addr, addrlen);
  142.   ps->laddrlen = addrlen;
  143.  
  144.   ps->socket_listen = pi_serial_listen;
  145.   ps->socket_accept = pi_serial_accept;
  146.   ps->socket_close = pi_serial_close;
  147.   ps->socket_send = pi_serial_send;
  148.   ps->socket_recv = pi_serial_recv;
  149.   ps->socket_tickle = pi_serial_tickle;
  150.  
  151.   return 0;
  152. }
  153.  
  154. /* Wait for an incoming connection */
  155.  
  156. static int pi_serial_listen(struct pi_socket *ps, int backlog)
  157. {
  158.   return 0;
  159. }
  160.  
  161. /* Accept an incoming connection */
  162.  
  163. static int pi_serial_accept(struct pi_socket *ps, struct sockaddr *addr, int *addrlen)
  164. {
  165.   struct pi_socket *accept;
  166.   struct cmp c;
  167.  
  168.   accept = malloc(sizeof(struct pi_socket));
  169.   memcpy(accept, ps, sizeof(struct pi_socket));
  170.  
  171.   if(accept->type == PI_SOCK_STREAM) {
  172.     accept->serial_read(accept, 200);
  173.     if(cmp_rx(accept, &c) < 0)
  174.       goto fail; /* Failed to establish connection, errno already set */
  175.     if ((c.version & 0xFF00) == 0x0100) {
  176.       if((unsigned long) accept->establishrate > c.baudrate) {
  177. #ifdef DEBUG
  178.         fprintf(stderr,"Rate %d too high, dropping to %ld\n",ps->establishrate,c.baudrate);
  179. #endif
  180.         accept->establishrate = c.baudrate;
  181.       }
  182.       accept->rate = accept->establishrate;
  183.       accept->version = c.version;
  184.       if(cmp_init(accept, accept->rate)<0)
  185.         goto fail;
  186.       pi_serial_flush(accept);
  187.  
  188.       if(accept->rate != 9600) {
  189.         accept->serial_changebaud(accept);
  190.       } else {
  191.         /* Apparently the device reconfigures its serial port even if the
  192.            baud rate is unchanged, so we'll need to pause a little so that
  193.            the next transmitted packet won't be lost */
  194.         struct timeval tv;
  195.         tv.tv_sec = 0;
  196.         tv.tv_usec = 50000;
  197.         select(0, 0, 0, 0, &tv);
  198.       }
  199.       accept->connected = 1;
  200.       accept->dlprecord = 0;
  201.     }else {
  202.       cmp_abort(ps, 0x80); /* 0x80 means the comm version wasn't compatible*/
  203.  
  204.       fprintf(stderr, "pi_socket connection failed due to comm version mismatch\n");
  205.       fprintf(stderr, " (expected version 01xx, got %4.4X)\n", c.version);
  206.  
  207.       errno = ECONNREFUSED;
  208.       goto fail;
  209.     }
  210.   } else {
  211.     accept->connected = 1;
  212.   }
  213.   
  214.   accept->sd = dup(ps->sd);
  215.  
  216.   pi_socket_recognize(accept);
  217.   
  218.   accept->laddr = malloc(ps->laddrlen);
  219.   accept->raddr = malloc(ps->raddrlen);
  220.   memcpy(accept->laddr, ps->laddr, ps->laddrlen);
  221.   memcpy(accept->raddr, ps->raddr, ps->raddrlen);
  222.   
  223.   accept->mac->ref++; /* Keep mac around even if the bound socket is closed */
  224.   accept->initiator = 0; /* We accepted the link, we did not initiate it */
  225.   
  226.   return accept->sd;
  227. fail:
  228.   free(accept);
  229.   return -1;
  230. }
  231.  
  232. /* Send msg on a connected socket */
  233.  
  234. static int pi_serial_send(struct pi_socket *ps, void *msg, int len, unsigned int flags)
  235. {
  236.   if (ps->type == PI_SOCK_STREAM)
  237.     return padp_tx(ps, msg, len, padData);
  238.   else
  239.     return syspkt_tx(ps, msg, len);
  240. }
  241.  
  242. /* Recv msg on a connected socket */
  243.  
  244. static int pi_serial_recv(struct pi_socket *ps, void *msg, int len, unsigned int flags)
  245. {
  246.   if (ps->type == PI_SOCK_STREAM)
  247.     return padp_rx(ps, msg, len);
  248.   else
  249.     return syspkt_rx(ps, msg, len);
  250. }
  251.  
  252. static int pi_serial_tickle(struct pi_socket *ps)
  253. {
  254.   if(ps->type == PI_SOCK_STREAM) {
  255.     struct padp pd;
  256.     int ret;
  257.     if (ps->busy || !ps->connected)
  258.       return -1;
  259.     pd.type = padTickle;
  260.     pd.flags = 0x00;
  261.     pd.size = 0x00;
  262.     ret = padp_tx(ps, (void *)&pd, 0, padTickle);
  263.     pi_serial_flush(ps);
  264.     return ret;
  265.   }
  266.   else {
  267.     errno = EOPNOTSUPP;
  268.     return -1;
  269.   }
  270. }
  271.  
  272. /* Close a connection, destroy the socket */
  273.  
  274. static int pi_serial_close(struct pi_socket * ps)
  275. {
  276.   if (ps->type == PI_SOCK_STREAM) {
  277.     if (ps->connected & 1) /* If socket is connected */
  278.       if (!(ps->connected & 2)) /* And it wasn't end-of-synced */
  279.         dlp_EndOfSync(ps->sd, 0);  /* then end sync, with clean status */
  280.   }
  281.   
  282.   if(ps->sd && (ps->sd != ps->mac->fd)) /* If device still has a /dev/null handle */
  283.     close(ps->sd); /* Close /dev/null handle */
  284.     
  285.   if(ps->mac->fd) { /* If device was opened */
  286.     if (ps->connected) {
  287.       pi_serial_flush(ps); /* Flush the device, and set baud rate back to the initial setting */
  288.       ps->rate = 9600; 
  289.       ps->serial_changebaud(ps);
  290.     }
  291.     if (--(ps->mac->ref) == 0) { /* If no-one is using the device, close it */
  292.       ps->serial_close(ps);
  293.       free(ps->mac);
  294.     }
  295.   }
  296.   
  297.   if(ps->laddr)
  298.     free(ps->laddr);
  299.   if(ps->raddr)
  300.     free(ps->raddr);
  301.  
  302.   return 0;
  303. }
  304.  
  305. int pi_serial_flush(struct pi_socket *ps)
  306. {
  307.   while(ps->serial_write(ps)) ;
  308.   return 0;
  309. }
  310.